home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Interactive Web Graphics with Shout 3D
/
Interactive Web Graphics With Shout 3D.iso
/
pc
/
Shout3Ddemo
/
Shout3d_runtime
/
codebase
/
applets
/
PyramidTestPanel.java
< prev
next >
Wrap
Text File
|
2000-09-01
|
7KB
|
246 lines
/**
Company: Eyematic Interfaces
Project: Shout3D 2.0 Sample Code
Class: PyramidTestPanel
Date: April 26, 1999
Description: Class for panel in which you click-drag to scale some pyramids
(C) Copyright Eyematic Interfaces, Inc. - 1997-2000 - All rights reserved
*/
package applets;
//Include this in order to be able to work
//with nodes in the custom_nodes package
import custom_nodes.*;
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.Date;
import java.net.URL;
import shout3d.*;
import shout3d.core.*;
/**
* PyramidTestPanel
*
* Shows how custom nodes can be added to Shout3D
* and used in applets.
*
* This applet creates three Pyramid nodes (a custom node in the
* custom_nodes directory) and then changes their fields when
* the user click-drags them.
*
*
* @author Dave Westwood
* @author Paul Isaacs
* @author Jim Stewartson
*/
public class PyramidTestPanel extends Shout3DPanel implements DeviceObserver {
// 3 Pyramids to be displayed and manipulated in the scene.
Pyramid pyramid0, pyramid1, pyramid2;
// For determining which pyramid is clicked with the mouse.
Picker myPicker;
Node[] pathToPick;
/**
* Constructor
*/
public PyramidTestPanel(Shout3DApplet applet){
super(applet);
}
float[] lavender = { .6f, .6f, 1 };
float[] seafoam = { .6f, 1f, .6f };
float[] gray = { .6f, .6f, .6f };
float[] pos0 = { -4, 0, 0 };
float[] pos1 = { 0, 0, 0 };
float[] pos2 = { 4, 0, 0 };
float[] rot0 = { 0, 1, 0, .8f };
float[] rot1 = { 0, 1, 0, 0 };
float[] rot2 = { 0, 1, 0, -.8f };
/**
*
* This method is automatically called by the parent class Shout3DPanel
* at the correct time during initialize().
*
* Subclasses should implement this to perform any custom initialization tasks.
*/
public void customInitialize() {
// Create the three pyramids
pyramid0 = new Pyramid();
pyramid1 = new Pyramid();
pyramid2 = new Pyramid();
// Get a transform for each pyramid, passing in pretty colors
Transform xf0 = createXf( pyramid0, lavender );
Transform xf1 = createXf( pyramid1, seafoam );
Transform xf2 = createXf( pyramid2, gray );
// Position them relative to each other:
xf0.translation.setValue(pos0);
xf1.translation.setValue(pos1);
xf2.translation.setValue(pos2);
xf0.rotation.setValue(rot0);
xf1.rotation.setValue(rot1);
xf2.rotation.setValue(rot2);
// Add to the scene
Node[] newKids = new Node[3];
newKids[0] = xf0;
newKids[1] = xf1;
newKids[2] = xf2;
getScene().addChildren(newKids);
// Move the camera back
Viewpoint myVP = (Viewpoint) getCurrentBindableNode("Viewpoint");
myVP.position.getValue()[2] = 10;
//notify
myVP.position.setValue(myVP.position.getValue());
// Allocate the picker
myPicker = getNewPicker();
//Watch for mouse events to do the picking.
this.addDeviceObserver(this, "MouseInput", null);
//Register to watch rendering. We'll want to change pyramid
//fields between renders so that field don't change during
//mid-multithreaded-render
getRenderer().addRenderObserver(this,null);
//Call the parent class
super.customInitialize();
}
/**
* Finalize
*/
protected void finalize()throws Throwable {
getRenderer().removeRenderObserver(this);
this.removeDeviceObserver(this, "MouseInput");
super.finalize();
}
Node pathTail;
Pyramid selectedPyramid;
float startWidth, startHeight, startDepth;
int startCursorX, startCursorY;
boolean waitingToChangeFields = false;
float nextWidth = 1;
float nextHeight = 1;
float nextDepth = 1;
/**
* Called when Mouse input is received.
*
* On mouse DOWN, checks for selection of one of the pyramids.
* Remembers which pyramid, and starting cursor location.
*
* On mouse DRAG, scales the selected pyramid.
* Horizontal motion scales width,depth.
* Vertical motion scales height.
*
*/
public boolean onDeviceInput(DeviceInput di, Object userData){
//No need to check type of deviceInput, only registered for Mouse Input.
MouseInput mi = (MouseInput) di;
if (mi.which == MouseInput.DOWN){
// Perform a pick and see if one of the pyramids was picked.
//
selectedPyramid = null;
pathToPick = myPicker.pickClosest(mi.x,mi.y);
if (pathToPick!=null && pathToPick.length > 0){
pathTail = pathToPick[pathToPick.length-1];
if (pathTail instanceof Pyramid){
selectedPyramid = (Pyramid) pathTail;
startCursorX = mi.x;
startCursorY = mi.y;
startWidth = selectedPyramid.width.getValue();
startHeight = selectedPyramid.height.getValue();
startDepth = selectedPyramid.depth.getValue();
//This input was used
return true;
}
}
}
else if (mi.which == MouseInput.DRAG){
// Based on mouse motion, change fields of currentPyramid.
// Width and depth change equally with horizontal motion,
// Height changes with vertical motion.
// Change by 1 unit every 100 pixels
nextWidth = startWidth + (float)(mi.x-startCursorX)/100;
nextHeight = startHeight - (float)(mi.y-startCursorY)/100;
nextDepth = startDepth + (float)(mi.x-startCursorX)/100;
// Clamp values to be > 0.1
if (nextWidth < 0.1) nextWidth = 0.1f;
if (nextHeight < 0.1) nextHeight = 0.1f;
if (nextDepth < 0.1) nextDepth = 0.1f;
// Don't set the field values now.
// Let them be set during onPreRender so that
// the field change occurs between renders.
waitingToChangeFields = true;
// Used the input
return true;
}
//Did not care about this input
return false;
}
/**
* Changing the fields should be done between renders.
* This is because rendering happens in a different thread,
* and updating the fields during a render can cause unpleasant
* flashing.
*
* Note that no onPostRender() method is implemented in this class,
* even though it is required for all classes implementing RenderObserver.
* This is because the super class implements RenderObserver fully
* and onPostRender is inherited.
* Hence this class needs only to override the onPreRender() method,
* making sure to call super.onPreRender(r,userData) within the body
* of the method.
*/
public void onPreRender(Renderer r, Object userData){
super.onPreRender(r, userData);
if (selectedPyramid != null && waitingToChangeFields){
selectedPyramid.width.setValue(nextWidth);
selectedPyramid.height.setValue(nextHeight);
selectedPyramid.depth.setValue(nextDepth);
waitingToChangeFields = false;
}
}
Transform createXf( Pyramid pyr, float[/*3*/] color ) {
Material newMat = new Material();
newMat.diffuseColor.setValue(color);
Appearance newApp = new Appearance();
newApp.material.setValue(newMat);
shout3d.core.Shape newShape = new shout3d.core.Shape();
newShape.geometry.setValue(pyr);
newShape.appearance.setValue( new Appearance[] { newApp });
Transform newXf = new Transform();
Node[] kids = new Node[1];
kids[0] = newShape;
newXf.addChildren(kids);
return newXf;
}
}